package com.ls.fw.data.search.impl.solrj.statement;

import java.util.List;

import org.apache.solr.client.solrj.SolrQuery;

import com.ls.fw.data.bean.Column;
import com.ls.fw.data.bean.From;
import com.ls.fw.data.bean.Group;
import com.ls.fw.data.bean.KeyValue;
import com.ls.fw.data.bean.MethodField;
import com.ls.fw.data.bean.MethodOrder;
import com.ls.fw.data.bean.Order;
import com.ls.fw.data.bean.SortFunctions;
import com.ls.fw.data.enums.AFunctions;
import com.ls.fw.data.exception.DataException;
import com.ls.fw.data.search.impl.solrj.domain.Constant;
import com.ls.fw.data.statement.Select;
import com.ls.fw.data.visitor.FieldVisitor;
import com.ls.fw.data.visitor.FromVisitor;
import com.ls.fw.data.visitor.GroupByVisitor;
import com.ls.fw.data.visitor.OrderByVisitor;
import com.ls.fw.data.visitor.SelectVisitor;

public class SelectParser extends BaseParser implements FieldVisitor,FromVisitor,GroupByVisitor,OrderByVisitor,SelectVisitor{

	private Select select = null;
	
	
	public SelectParser(Select select) {
		this.select = select;
		this.visit(select);
	}
	
	@Override
	public void visit(Select select) {
		WhereParser w = new WhereParser(select.getTable(),select.getWhere());
		w.parse(query);
		this.makeLimit(query, select);
		List<Column> list = select.getFields();
		if(list==null || list.isEmpty()){
			query.addField("*");
			query.addField(Constant.SCORE_FILED);
		}else{
			for (Column column : list) { 
				column.accept(this);
			}
		}
		this.makeOrderBy(query, select);
		if(select.isGroup){
			this.makeGroupBy(query, select);
		}
	}
	
	
	/**
	 * 处理分组
	 * @author ls
	 * 2014年11月22日下午4:16:26 
	 * @param query
	 * @param select
	 * @return
	 */
	public SolrQuery makeGroupBy(final SolrQuery query, final Select select){
			//parameters only for grouping result  
		   List<Group> list = select.getGroupBys();
		   if(!select.isGroup || list==null || list.isEmpty()){
			   return query;
		   }
		   StringBuilder sb = new StringBuilder();
		   int index = 0;
		   for (Column column : list) {
			   if(index>0){
				   sb.append(",");
			   }
			   sb.append(column.getName());
			   index ++;
			   //目前只支持单个分组条件
			   break;
		   }
	       query.set("group", "true");         
	       query.set("group.field", sb.toString());  
		   query.set("group.format", "grouped"); //default:simple, other:grouped  
			// when /*group.format=simple and */ group.main=true, just return the documentList only!!!   
	       query.set("group.main", "false");   
	       query.set("group.ngroups", "true");  
	       query.set("group.truncate", "true"); //default is false;  
	       query.set("group.cache.percent", "50"); //default is 0;  
	       query.set("group.facet", "true");  
	       //group.limit Defaults to 1.
	       query.set("group.offset", 0);
		return query;
	}
	
	
	/**
	 * 处理排序字段
	 * @author ls
	 * 2014年11月22日下午4:12:51 
	 * @param query
	 * @param select
	 * @return
	 */
	public SolrQuery makeOrderBy(final SolrQuery query, final Select select){
		List<Order> list = select.getOrderBys();
		if(select.isGroup){
			int index = 0;		   
			StringBuilder sb = new StringBuilder();
			for (Order order : list) {
				if(index>0){
					sb.append(",");
				}
				sb.append(order.getName()+" "+order.getType().getName());
				index ++;
			}
			query.set("group.sort",sb.toString());  
		}else{
			for (Order order : list) {
				if(order instanceof MethodOrder){
					String str = query.get("sort");
					StringBuilder sb = new StringBuilder();
					if(!(str==null || str.equals(""))){
						sb.append(str+",");  
					}
					sb.append(this.handlMethodOrder((MethodOrder) order));
					query.set("sort", sb.toString());  //default score asc.
				}else{
					query.addSort(order.getName(), SolrQuery.ORDER.valueOf(order.getType().getName()));
				}
			}
		}
		return query;
	}
	
	
	private String handlMethodOrder(final MethodOrder methodOrder){
		SortFunctions af = SortFunctions.get(methodOrder.getName());
		StringBuilder sb = new StringBuilder();
		switch(af){
			case AVG:
				break;
			case COUNT:
				break;
			case SUM:
				sb.append(this.handlSumSort(methodOrder));
				break; 
			case UNKWON:
				if(methodOrder.isDynamic()){
					sb.append(this.handlDefaultSort(methodOrder));
				}else{
					throw new DataException("暂不支持该排序方法！");
				}
				break; 
			default:
				throw new DataException("暂不支持该排序方法！");
		}
		return sb.toString();
	}
	
	private String handlDefaultSort(final MethodOrder methodOrder){
		StringBuilder sb = new StringBuilder();
		sb.append(methodOrder.getName());
		sb.append("(");
		List<KeyValue> list = methodOrder.getParams();
		int index = 0;
		for (KeyValue keyValue : list) {
			if(index > 0){
				sb.append(",");
			}
			sb.append(keyValue.value);
			index++;
		}
		sb.append(") "+methodOrder.getType().getName());
		return sb.toString();
	}
	
	private String handlSumSort(final MethodOrder methodOrder){
		StringBuilder sb = new StringBuilder();
		sb.append("sum(");
		List<KeyValue> list = methodOrder.getParams();
		int index = 0;
		for (KeyValue keyValue : list) {
			if(index > 0){
				sb.append(",");
			}
			sb.append(keyValue.value);
			index++;
		}
		sb.append(") "+methodOrder.getType().getName());
		return sb.toString();
	}
	
	
	
	/**
	 * 处理分页
	 * @author ls
	 * 2014年11月22日下午4:16:17 
	 * @param query
	 * @param select
	 * @return
	 */
	public SolrQuery makeLimit(final SolrQuery query, final Select select){
		if(select.isGroup){
			query.set("group.limit", select.getRowCount());  
            query.set("group.offset", select.getOffset());
		}else{
			query.setStart(select.getOffset());
			query.setRows(select.getRowCount());
		}
		return query;
	}
	
	
	@Override
	public void visit(Column column) {
		if (column instanceof MethodField) {
			AFunctions  af = AFunctions.get(column.getName());
			switch(af){
				case AVG:
					break;
				case COUNT:
					query.setRows(0);
					break;
				case MAX:
					break;
				case MIN:
					break;
				case SUM:
					break;
				case UNKWON:
				default:
					throw new DataException("暂不支持该聚合函数： " + column);
			}

		} else if (column instanceof Column) {
			query.addField(column.getName());
			if(column.getName().equals("*")){
				query.addField(Constant.SCORE_FILED);
			}
		} else {
			throw new DataException("暂不支持该显示类型的字段：" + column);
		}
	}

	@Override
	public void visit(Order order) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(From field) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(Group field) {
		// TODO Auto-generated method stub
		 
	}

}
